module command(
  input wire CCLK,
  input wire ROTA,
  input wire ROTB,
  input wire BTN0,              // reset
  input wire rotary_pushbtn,    // rotary pushbutton

  output wire SPISCK,
  output wire SPIMOSI,
  output wire SPIMISO,
  output wire SF_OE,
  output wire SF_WE,
  output wire AMPSD,
  output wire SFCE,     // parallel flash prom
  output wire SPISF,
  output wire FPGAIB,   // platform flash prom
  output wire AMPCS,    // pre-amp
  output wire DACCS,    // dac converter
  output wire ADCON,    // adc
  output wire LCDE,
  output wire LCDRS,
  output wire LCDRW,
  output wire DACCLR,
  output wire [3:0] LCDDAT,
  output wire [7:0] LED
  );

localparam IDLE = 3'b00;
localparam WRITE_TO_SCREEN = 3'b01;
localparam WAIT_DONE = 3'b11;
localparam SET_ADDR = 3'b100;
localparam MENU_MASTER = 5'b00101;
localparam EDIT_FREQ = 5'b00110;
localparam EDIT_WAVEFORM_TYPE = 5'b00111;
localparam EDIT_DIGIT_4 = 5'b01000;
localparam EDIT_DIGIT_3 = 5'b01001;
localparam EDIT_DIGIT_2 = 5'b01010;
localparam EDIT_DIGIT_1 = 5'b01011;
localparam EDIT_DIGIT_0 = 5'b01100;
localparam CHANGE_CURRENT_WAVEFORM = 5'b01101;
localparam SHIFT_CURSOR_LEFT = 5'b01110;
localparam SHIFT_CURSOR_RIGHT = 5'b01111;
localparam WRITE_THE_WORD_FREQUENCY = 5'b10000;
localparam WRITE_THE_WORD_WAVEFORM = 5'b10001;
localparam SET_THAT_CURSOR = 5'b10010;
localparam WRITE_TO_SCREEN_FROM_FREQ = 5'b10011;
localparam DISPLAY_SQUARE_WAVEFORM = 5'b10100;
localparam DISPLAY_TRIANGLE_WAVEFORM = 5'b10101;
localparam DISPLAY_SAWTOOTH_WAVEFORM = 5'b10110;

wire          CLKDV_OUT;      // divided clock, output of DCM
wire          CLK0_OUT;
reg           do_init;
wire          init_done;
wire          reset_done;
reg           do_write_data;
reg   [7:0]   data_to_write;
reg   [6:0]   cursor_addr;
reg           address_is_set;
wire          rotary_pushbtn_debounced;
wire          rotary_pushbtn_oneshot;
wire          rotary_event;
wire          rotary_left;
wire          send_data_done;
reg           line;             // top or bottom line?
reg           do_shift_cursor;
reg           shift_direction;  // right = 1, left = 0
reg           menu_type;
reg   [1:0]   current_waveform;
reg           cursor_has_been_set;
reg           do_set_dd_ram_addr;
wire          set_dd_ram_addr_done;
reg           count_enable;
wire          ena;
reg   [11:0]  dac_b;
reg   [127:0] string_to_display;
// reg   [127:0] prev_string;
wire  [7:0]   rotary_count;
reg   [4:0]   display_counter;
reg   [6:0]   dd_ram_addr;
reg   [4:0]   current_state, next_state, return_to_state;
reg   [7:0]   current_rot, prev_rot;
reg   [3:0]   digit_4_data,digit_3_data,digit_2_data,digit_1_data,digit_0_data;
wire  [23:0]  phase;
wire  [23:0]  frequency;
wire  [35:0]  CONTROL;


always @(posedge CLKDV_OUT or posedge BTN0) begin
  if(BTN0)begin
    current_rot <= 0;
    prev_rot <= 0;
  end else begin
    current_rot <= rotary_count;
    prev_rot <= current_rot;
  end
end

always @(posedge CLKDV_OUT or posedge BTN0) begin
  if(BTN0) begin
  display_counter <= 5'h0;  // tracks the current cell to write to
  do_init <= 1'b1;          // do the initialization sequence
  line <= 1'b0;             // print on the top line
  string_to_display <= 1'b0;// initialize the string to zero
  do_write_data <= 1'b0;
  do_set_dd_ram_addr <= 1'b0;
  next_state <= 1'b0;
  dd_ram_addr <= 1'b0;
  shift_direction <= 1'b0;
  do_shift_cursor <= 1'b0;
  menu_type <= 1'b0;
  digit_4_data <= 1'b0;
  digit_3_data <= 1'b0;
  digit_2_data <= 1'b0;
  digit_1_data <= 1'b0;
  digit_0_data <= 1'b0;
  current_waveform <= 1'b0;
  return_to_state <= 1'b0;
  address_is_set <= 1'b0;
  cursor_has_been_set <= 1'b0;
  count_enable <= 1'b0;
  end else begin

  case(current_state)
    IDLE: begin
      do_write_data <= 1'b0;
      if(~init_done) do_init <= 1'b1;
      else if(~reset_done) begin
        do_init <= 1'b0;
        next_state <= IDLE;

      ///////////////////// done resetting and initializing if past here
      end else if(string_to_display != "Frequency       " || string_to_display != "Waveform        ")begin
        next_state <= MENU_MASTER;
        count_enable <= 1'b1;
        menu_type <= 1'b0;          // default to display "Frequency"
      end else if(rotary_pushbtn_oneshot)begin
        if(string_to_display == "Frequency       " ) begin
          next_state <= EDIT_FREQ;
        end else begin
          next_state <= EDIT_WAVEFORM_TYPE;
        end
      end else if(current_rot != prev_rot) begin
        menu_type <= ~menu_type;
        next_state <= MENU_MASTER;
        line <= 0;
        do_set_dd_ram_addr <= 1'b0;
        do_write_data <= 1'b0;
      end else begin
        do_init <= 1'b0;
        next_state <= IDLE;
      end
    end

    // state 1
    WRITE_TO_SCREEN: begin
      if(~address_is_set) begin
        next_state <= SET_ADDR;
        do_set_dd_ram_addr <= 1'b1;
      end else if(display_counter != 1'b0) begin
        next_state <= WAIT_DONE;                  // state 3
        do_write_data <= 1'b1;
      end else begin                              // display counter == 0 if here.  done.
        next_state <= return_to_state;
      end
    end

    // state 3
    WAIT_DONE: begin
      if(send_data_done) begin
        next_state <= WRITE_TO_SCREEN;            // state 1
        do_write_data <= 1'b0;
        display_counter <= display_counter - 1'b1;
      end else begin
        next_state <= WAIT_DONE;                  // state 3
        do_write_data <= 1'b1;
        end
      end

    // state 4  -- before moving to this state, set the do_set_dd_ram_addr flag = 1.
    SET_ADDR: begin
    do_set_dd_ram_addr <= 1'b0;
    if(line)begin                         // write on lower line
      //dd_ram_addr <= 7'h40;             // this is the address of the lower line
      if(set_dd_ram_addr_done) begin      // stay in this state until done setting the new address
        address_is_set <= 1'b1;           // the flag that allows WRITE_TO_SCREEN to continue
        next_state <= WRITE_TO_SCREEN;    // state 3
        end else next_state <= SET_ADDR;  // state 4
    end else begin                        // write on upper line
      //dd_ram_addr <= 7'h00;             // address of upper line --------------->> address must now be set before transferring control to SET_ADDR.
      if(set_dd_ram_addr_done)begin       // stay in this state until done setting the new address
        address_is_set <= 1'b1;           // the flag that allows WRITE_TO_SCREEN to continue
        next_state <= WRITE_TO_SCREEN;    // state 3
      end else next_state <= SET_ADDR;    // state 4
    end
    end

    // state 5
    MENU_MASTER: begin
    if(current_rot != prev_rot) menu_type <= ~menu_type;
    else if(menu_type == 1'b0) begin
      if(string_to_display != "Frequency       ") begin
        next_state <= WRITE_THE_WORD_FREQUENCY;   // state 5'h10
      end else if(rotary_pushbtn_oneshot)begin
        next_state <= EDIT_FREQ;                  // state 6
      end else if(!cursor_has_been_set) begin
        next_state <= SET_THAT_CURSOR;            // state 5'h12
      end else next_state <= MENU_MASTER;         // state 5
    end
    else begin
      if(string_to_display != "Waveform        ") begin
        next_state <= WRITE_THE_WORD_WAVEFORM;    // state 5'h10
      end else if(rotary_pushbtn_oneshot)begin
        next_state <= EDIT_WAVEFORM_TYPE;         // state 7
    end else if(!cursor_has_been_set) begin
      next_state <= SET_THAT_CURSOR;              // state 5'h12
      end else next_state <= MENU_MASTER;         // state 5
      end
    end

    // state 6
    EDIT_FREQ: begin
      if(string_to_display[127:88] != {(convert(digit_4_data)),(convert(digit_3_data)),(convert(digit_2_data)),(convert(digit_1_data)),(convert(digit_0_data))})begin
        string_to_display [127:0] <= {(convert(digit_4_data)),(convert(digit_3_data)),(convert(digit_2_data)),(convert(digit_1_data)),(convert(digit_0_data))," Hz ",56'h7F202020202020};
        return_to_state <= EDIT_FREQ;
        next_state <= WRITE_TO_SCREEN;  // state 1
        display_counter <= 5'h10;
        dd_ram_addr <= 1'b0;
        address_is_set <= 1'b0;
        cursor_has_been_set <= 1'b0;
        count_enable <= 1'b0;           // this is tied to reset in the counter so it starts up = 0.
      end else if(!cursor_has_been_set) begin
        return_to_state <= EDIT_FREQ;   // state 6
        next_state <= WRITE_TO_SCREEN;  // state 1
        display_counter <= 5'h0;
        dd_ram_addr <= 5'h0;
        cursor_has_been_set <= 1'b1;
        address_is_set <= 1'b0;
      end else if(rotary_pushbtn_oneshot) begin
      count_enable <= 1'b1;           // this is tied to reset in the counter so it starts up = 0.
        case(cursor_addr)
          7'b000:        next_state <= EDIT_DIGIT_4; // state 8
          7'b001:        next_state <= EDIT_DIGIT_3; // state 9
          7'b010:        next_state <= EDIT_DIGIT_2; // state A
          7'b011:        next_state <= EDIT_DIGIT_1; // state B
          7'b100:        next_state <= EDIT_DIGIT_0; // state C
          default:        begin
                          next_state <= IDLE;
                          end
        endcase
    end else if(current_rot < prev_rot)begin
      next_state <= SHIFT_CURSOR_LEFT;        // state E
      shift_direction <= 1'b0;
      do_shift_cursor <= 1'b1;
    end else if(current_rot > prev_rot) begin
      next_state <= SHIFT_CURSOR_RIGHT;       // state F
      shift_direction <= 1'b1;
      do_shift_cursor <= 1'b1;
    end
    end

    // state 7
    EDIT_WAVEFORM_TYPE: begin
    if(current_rot!=prev_rot) begin
        if(current_rot < prev_rot) begin
          if(current_waveform == 1'b0) current_waveform <= 2'b10;
          else current_waveform <= current_waveform - 1'b1;
        end else if(current_rot > prev_rot) begin
          if(current_waveform == 2'b10) current_waveform <= 2'b0;
          else current_waveform <= current_waveform + 1'b1;
        end
        case(current_waveform)
          2'b00:  next_state <= DISPLAY_SQUARE_WAVEFORM;
          2'b01:  next_state <= DISPLAY_TRIANGLE_WAVEFORM;
          2'b10:  next_state <= DISPLAY_SAWTOOTH_WAVEFORM;
          default: next_state <= IDLE;
        endcase
        end
    else if(rotary_pushbtn_oneshot) begin
        next_state <= IDLE;
      end else next_state <= EDIT_WAVEFORM_TYPE;
    end

    // state 5'h14
    DISPLAY_SQUARE_WAVEFORM: begin
      if(string_to_display != "Square          ")begin
        string_to_display <= "Square          ";
        return_to_state <= EDIT_WAVEFORM_TYPE;          // store the state to return to after WRITE_TO_SCREEN's done.
        next_state <= WRITE_TO_SCREEN;               // write_to_screen handles LCD display traffic
        display_counter <= 5'h10;                    // rewrite entire line
        dd_ram_addr <= 1'b0;                         // this is the address where it goes
        address_is_set <= 1'b0;                      // when SET_ADDR is done, this flag will allow WRITE_TO_SCREEN to proceed.
        cursor_has_been_set <= 1'b0;
      end else next_state <= EDIT_WAVEFORM_TYPE;
    end


    // state 5'h15
    DISPLAY_TRIANGLE_WAVEFORM: begin
      if(string_to_display != "Triangle        ")begin
        string_to_display <= "Triangle        ";
        return_to_state <= EDIT_WAVEFORM_TYPE;          // store the state to return to after WRITE_TO_SCREEN's done.
        next_state <= WRITE_TO_SCREEN;               // write_to_screen handles LCD display traffic
        display_counter <= 5'h10;                    // rewrite entire line
        dd_ram_addr <= 1'b0;                         // this is the address where it goes
        address_is_set <= 1'b0;                      // when SET_ADDR is done, this flag will allow WRITE_TO_SCREEN to proceed.
        cursor_has_been_set <= 1'b0;
      end else next_state <= EDIT_WAVEFORM_TYPE;
    end


    // state 5'h16
    DISPLAY_SAWTOOTH_WAVEFORM: begin
      if(string_to_display != "Sawtooth        ")begin
        string_to_display <= "Sawtooth        ";
        return_to_state <= EDIT_WAVEFORM_TYPE;          // store the state to return to after WRITE_TO_SCREEN's done.
        next_state <= WRITE_TO_SCREEN;               // write_to_screen handles LCD display traffic
        display_counter <= 5'h10;                    // rewrite entire line
        dd_ram_addr <= 1'b0;                         // this is the address where it goes
        address_is_set <= 1'b0;                      // when SET_ADDR is done, this flag will allow WRITE_TO_SCREEN to proceed.
        cursor_has_been_set <= 1'b0;
      end else next_state <= EDIT_WAVEFORM_TYPE;
    end

    // state 8
    EDIT_DIGIT_4: begin
      // if the corresponding digit has changed, write the current value,
      //   then return to this state and continue.
      if(string_to_display [127:120] != (convert(digit_4_data))) begin
        string_to_display [127:120] <= (convert(digit_4_data));
        return_to_state <= EDIT_DIGIT_4;          // store the state to return to after WRITE_TO_SCREEN's done.
        next_state <= WRITE_TO_SCREEN;            // write_to_screen handles LCD display traffic
        display_counter <= 5'h10;                 // rewrite entire line
        dd_ram_addr <= 1'b0;                      // this is the address where it goes
        address_is_set <= 1'b0;                   // when SET_ADDR is done, this flag will allow WRITE_TO_SCREEN to proceed.
        cursor_has_been_set <= 1'b0;

      // immediately after writing the new digit, set the cursor to the right location.
      end else if(!cursor_has_been_set) begin
        return_to_state <= EDIT_DIGIT_4;
        next_state <= WRITE_TO_SCREEN_FROM_FREQ;
      end else if(rotary_pushbtn_oneshot)begin    // the exit signal - the value displayed is set
        next_state <= EDIT_FREQ;                  // state 6
      end else if(current_rot<prev_rot)begin      // counterclockwise turn - decrement
      if(digit_4_data == 4'h0) digit_4_data <= 4'h2;
        else                   digit_4_data <= digit_4_data - 1'b1;
      end else if(current_rot>prev_rot)begin      // clockwise turn - increment
      if(digit_4_data == 4'h2) digit_4_data <= 4'h0;
        else                   digit_4_data <= digit_4_data + 1'b1;
      end else next_state <= EDIT_DIGIT_4;        // nothing's happened yet.  stay here til something does.
    end

    // state 9
    EDIT_DIGIT_3: begin
      if(string_to_display [119:112] != (convert(digit_3_data))) begin
        string_to_display [119:112] <= (convert(digit_3_data));
        return_to_state <= EDIT_DIGIT_3;          // store the state to return to after WRITE_TO_SCREEN's done.
        next_state <= WRITE_TO_SCREEN;            // write_to_screen handles LCD display traffic
        display_counter <= 5'h10;                 // rewrite entire line
        dd_ram_addr <= 1'b0;                      // this is the address where it goes
        address_is_set <= 1'b0;                   // when SET_ADDR is done, this flag will allow WRITE_TO_SCREEN to proceed.
        cursor_has_been_set <= 1'b0;

      // immediately after writing the new digit, set the cursor to the right location.
      end else if(!cursor_has_been_set) begin
        return_to_state <= EDIT_DIGIT_3;
        next_state <= WRITE_TO_SCREEN_FROM_FREQ;
      end else if(rotary_pushbtn_oneshot)begin    // the exit signal - the value displayed is set
        next_state <= EDIT_FREQ;                  // state 6
      end else if(current_rot<prev_rot)begin      // counterclockwise turn - decrement
      if(digit_3_data == 4'h0) digit_3_data <= 4'h9;
        else                   digit_3_data <= digit_3_data - 1'b1;
      end else if(current_rot>prev_rot)begin      // clockwise turn - increment
      if(digit_3_data == 4'h9) digit_3_data <= 4'h0;
        else                   digit_3_data <= digit_3_data + 1'b1;
      end else next_state <= EDIT_DIGIT_3;        // nothing's happened yet.  stay here til something does.
    end

    // state A
    EDIT_DIGIT_2: begin
      if(string_to_display [111:104] != (convert(digit_2_data))) begin
        string_to_display [111:104] <= (convert(digit_2_data));
        return_to_state <= EDIT_DIGIT_2;          // store the state to return to after WRITE_TO_SCREEN's done.
        next_state <= WRITE_TO_SCREEN;            // write_to_screen handles LCD display traffic
        display_counter <= 5'h10;                 // rewrite entire line
        dd_ram_addr <= 1'b0;                      // this is the address where it goes
        address_is_set <= 1'b0;                   // when SET_ADDR is done, this flag will allow WRITE_TO_SCREEN to proceed.
        cursor_has_been_set <= 1'b0;

      // immediately after writing the new digit, set the cursor to the right location.
      end else if(!cursor_has_been_set) begin
        return_to_state <= EDIT_DIGIT_2;
        next_state <= WRITE_TO_SCREEN_FROM_FREQ;
      end else if(rotary_pushbtn_oneshot)begin    // the exit signal - the value displayed is set
        next_state <= EDIT_FREQ;                  // state 6
      end else if(current_rot<prev_rot)begin      // counterclockwise turn - decrement
      if(digit_2_data == 4'h0) digit_2_data <= 4'h9;
        else                   digit_2_data <= digit_2_data - 1'b1;
      end else if(current_rot>prev_rot)begin      // clockwise turn - increment
      if(digit_2_data == 4'h9) digit_2_data <= 4'h0;
        else                   digit_2_data <= digit_2_data + 1'b1;
      end else next_state <= EDIT_DIGIT_2;        // nothing's happened yet.  stay here til something does.
    end

    // state B
    EDIT_DIGIT_1: begin
      if(string_to_display [103:96] != (convert(digit_1_data))) begin
        string_to_display [103:96] <= (convert(digit_1_data));
        return_to_state <= EDIT_DIGIT_1;          // store the state to return to after WRITE_TO_SCREEN's done.
        next_state <= WRITE_TO_SCREEN;            // write_to_screen handles LCD display traffic
        display_counter <= 5'h10;                 // rewrite entire line
        dd_ram_addr <= 1'b0;                      // this is the address where it goes
        address_is_set <= 1'b0;                   // when SET_ADDR is done, this flag will allow WRITE_TO_SCREEN to proceed.
        cursor_has_been_set <= 1'b0;

      // immediately after writing the new digit, set the cursor to the right location.
      end else if(!cursor_has_been_set) begin
        return_to_state <= EDIT_DIGIT_1;
        next_state <= WRITE_TO_SCREEN_FROM_FREQ;
      end else if(rotary_pushbtn_oneshot)begin    // the exit signal - the value displayed is set
        next_state <= EDIT_FREQ;                  // state 6
      end else if(current_rot<prev_rot)begin      // counterclockwise turn - decrement
      if(digit_1_data == 4'h0) digit_1_data <= 4'h9;
        else                   digit_1_data <= digit_1_data - 1'b1;
      end else if(current_rot>prev_rot)begin      // clockwise turn - increment
      if(digit_1_data == 4'h9) digit_1_data <= 4'h0;
        else                   digit_1_data <= digit_1_data + 1'b1;
      end else next_state <= EDIT_DIGIT_1;        // nothing's happened yet.  stay here til something does.
    end

    // state C
    EDIT_DIGIT_0: begin
      if(string_to_display [95:88] != (convert(digit_0_data))) begin
        string_to_display [95:88] <= (convert(digit_0_data));
        return_to_state <= EDIT_DIGIT_0;          // store the state to return to after WRITE_TO_SCREEN's done.
        next_state <= WRITE_TO_SCREEN;            // write_to_screen handles LCD display traffic
        display_counter <= 5'h10;                 // rewrite entire line
        dd_ram_addr <= 1'b0;                      // this is the address where it goes
        address_is_set <= 1'b0;                   // when SET_ADDR is done, this flag will allow WRITE_TO_SCREEN to proceed.
        cursor_has_been_set <= 1'b0;

      // immediately after writing the new digit, set the cursor to the right location.
      end else if(!cursor_has_been_set) begin
        return_to_state <= EDIT_DIGIT_0;
        next_state <= WRITE_TO_SCREEN_FROM_FREQ;
      end else if(rotary_pushbtn_oneshot)begin    // the exit signal - the value displayed is set
        next_state <= EDIT_FREQ;                  // state 6
      end else if(current_rot<prev_rot)begin      // counterclockwise turn - decrement
      if(digit_0_data == 4'h0) digit_0_data <= 4'h9;
        else                   digit_0_data <= digit_0_data - 1'b1;
      end else if(current_rot>prev_rot)begin      // clockwise turn - increment
      if(digit_0_data == 4'h9) digit_0_data <= 4'h0;
        else                   digit_0_data <= digit_0_data + 1'b1;
      end else next_state <= EDIT_DIGIT_0;        // nothing's happened yet.  stay here til something does.
    end

    // state D
    CHANGE_CURRENT_WAVEFORM: begin
    if(current_waveform == 1'b0) begin
      string_to_display[127:16] <= "Triangle      ";
      //TODO: change the output to the DAC
      end else if(current_waveform == 1'b1) begin
        string_to_display[127:16] <= "Square        ";
      // TODO: change the output to the DAC
      end
    end

    // state E
    SHIFT_CURSOR_LEFT: begin
      do_shift_cursor <= 1'b0;
      if(send_data_done)  next_state <= EDIT_FREQ;
      else                next_state <= SHIFT_CURSOR_LEFT;
    end

    // state F
    SHIFT_CURSOR_RIGHT: begin
      do_shift_cursor <= 1'b0;
      if(send_data_done)  next_state <= EDIT_FREQ;
      else                next_state <= SHIFT_CURSOR_RIGHT;
    end

    // state 5'h10
    WRITE_THE_WORD_FREQUENCY: begin
      string_to_display <= "Frequency       ";
      return_to_state <= MENU_MASTER;
      next_state <= WRITE_TO_SCREEN;
      display_counter <= 5'h10;
      dd_ram_addr <= 7'h0;
      address_is_set <= 1'b0;
      cursor_has_been_set <= 1'b0;                    // flag to signify the cursor needs to be set now.
    end

    // state 5'h11
    WRITE_THE_WORD_WAVEFORM: begin
      string_to_display <= "Waveform        ";
      return_to_state <= MENU_MASTER;
      next_state <= WRITE_TO_SCREEN;
      display_counter <= 5'h10;
      dd_ram_addr <= 7'h0;
      address_is_set <= 1'b0;
      cursor_has_been_set <= 1'b0;
    end

    // state 5'h12
    SET_THAT_CURSOR: begin
      return_to_state <= MENU_MASTER;
      next_state <= WRITE_TO_SCREEN;
      display_counter <= 5'h0;
      dd_ram_addr <= {4'b0000, cursor_addr};
      cursor_has_been_set <= 1'b1;
    end

    // state 5'h13
    WRITE_TO_SCREEN_FROM_FREQ: begin
      next_state <= WRITE_TO_SCREEN;
      display_counter <= 5'h0;
      dd_ram_addr <= {4'b0000, cursor_addr};
      cursor_has_been_set <= 1'b1;
      address_is_set <= 1'b0;
    end

  endcase
  end
end

always@* begin
case(current_waveform)
  2'b00: dac_b = {12{phase[23]}};         // square
  2'b01: dac_b = phase[23:12];            // triangle
  2'b10: dac_b = phase[23:12];            // sawtooth
  default: dac_b = 12'b0;
  endcase
end

always @(posedge CLKDV_OUT or posedge BTN0) begin
  if(BTN0)        data_to_write <= 1'b0;
  else begin
    case(display_counter)
      5'h10: data_to_write <= string_to_display[127:120];
      5'h0f: data_to_write <= string_to_display[119:112];
      5'h0e: data_to_write <= string_to_display[111:104];
      5'h0d: data_to_write <= string_to_display[103:96];
      5'h0c: data_to_write <= string_to_display[95:88];
      5'h0b: data_to_write <= string_to_display[87:80];
      5'h0a: data_to_write <= string_to_display[79:72];
      5'h09: data_to_write <= string_to_display[71:64];
      5'h08: data_to_write <= string_to_display[63:56];
      5'h07: data_to_write <= string_to_display[55:48];
      5'h06: data_to_write <= string_to_display[47:40];
      5'h05: data_to_write <= string_to_display[39:32];
      5'h04: data_to_write <= string_to_display[31:24];
      5'h03: data_to_write <= string_to_display[23:16];
      5'h02: data_to_write <= string_to_display[15:8];
      5'h01: data_to_write <= string_to_display[7:0];
      endcase
  end
end

always @(negedge CLKDV_OUT or posedge BTN0) begin
  if(BTN0)  current_state <= IDLE;
  else      current_state <= next_state;
end

// always @(negedge CLKDV_OUT or posedge BTN0) begin
  // if(BTN0)  prev_string <= IDLE;
  // else      prev_string <= string_to_display;
// end

always @* begin
  cursor_addr = rotary_count[3:0];
end

transaction TXN(
  .clk(CLKDV_OUT),
  .reset(BTN0),
  .do_init(do_init),
  .reset_done(reset_done),
  .do_write_data(do_write_data),
  .data_to_write(data_to_write),
  .do_shift_cursor(do_shift_cursor),
  .shift_direction(shift_direction),
  .do_set_dd_ram_addr(do_set_dd_ram_addr),
  .dd_ram_addr(dd_ram_addr),
  .LCDE_q(LCDE),
  .LCDRS_q(LCDRS),
  .LCDRW_q(LCDRW),
  .LCDDAT_q(LCDDAT),
  .init_done(init_done),
  .send_data_done(send_data_done),
  .set_dd_ram_addr_done(set_dd_ram_addr_done)
);

debounce_sync rot_btn_debouncer(
  .clock(CLKDV_OUT),
  .reset(BTN0),
  .async_in(rotary_pushbtn),
  .sync_out(rotary_pushbtn_debounced)
);
oneshot rot_btn_oneshotter(
  .reset(BTN0),                           // button north
  .clock(CLKDV_OUT),                      // comes from the clock divider
  .get_debounce(rotary_pushbtn_debounced),          // comes from the BTN1_debouncer
  .get_oneshot(rotary_pushbtn_oneshot)          // output is used in command layer
);

rotary_decode ROT_DEC(
  .clock(CLKDV_OUT),
  .reset(BTN0),
  .rotary_a(ROTA),
  .rotary_b(ROTB),
  .rotary_event(rotary_event),
  .rotary_left(rotary_left)
  );

counter_updown counter_updown(
  .clock(CLKDV_OUT),
  .reset(~count_enable),          // reset count to zero in between uses.  active high reset.
  .enable(rotary_event),
  .direction(~rotary_left),
  .out(rotary_count)
  );

// NCO generates phase from frequency
nco nco(
  .clock(CLKDV_OUT),
  .reset(BTN0),
  .enable(1'b1),
  .frequency_in(frequency),
  .phase_out(phase)
  );  
  
  
spi_io spi_io(
  .clock(CLKDV_OUT),
  .reset(BTN0),
  .spi_sck(SPISCK),
  .spi_sdo(SPIMOSI),
  .spi_sdi(SPIMISO),
  .spi_dac_cs(DACCS),
  .spi_amp_cs(AMPCS),
  .spi_adc_conv(ADCON),
  .dac_b_in(dac_b)
);
  
  
function [7:0] convert (input [3:0] nibble);
  begin
    convert = (nibble<8'hA)?nibble+8'h30:nibble+8'h37;
  end
endfunction

// clock_divider_tb CLK_DIV_TB(
// .clk_in(CCLK),
// .reset(BTN0),
// .clk_out(CLKDV_OUT)
// );

clock_divider CLK_DIV(
    .CLKIN_IN(CCLK),
    .RST_IN(BTN0),
    .CLKDV_OUT(CLKDV_OUT),
    .CLK0_OUT(CLK0_OUT)
    );

  icon icon (
      .CONTROL0(CONTROL) // INOUT BUS [35:0]
  );

  ila ila (
      .CONTROL(CONTROL), // INOUT BUS [35:0]
      .CLK(CLK0_OUT), // IN
    /*add things to the front of this list so you don't have to re-name everything in chipscope...*/
      .TRIG0({digit_4_data,set_dd_ram_addr_done,BTN0,reset_done,CLKDV_OUT,rotary_pushbtn_oneshot,current_state, next_state}) // IN BUS [23:0]
  );

assign frequency = {4'b0,digit_4_data,digit_3_data,digit_2_data,digit_1_data,digit_0_data};
assign LED [4:0] = current_state;   // debug
assign LED [7:5] = rotary_count;    // debug


assign SF_OE = 1'b1;      // strataflash output enable
assign SFCE   = 1'b1;     // strataflash chip enable
assign SF_WE = 1'b1;      // strataflash write enable
assign FPGAIB = 1'b0;     // platform flash
// assign SPISCK = 1'b0;
// assign SPIMOSI= 1'b0;
assign SPISF  = 1'b1;     // spi rom chip select
assign AMPSD = 1'b1;      // spi_amp_shdn
assign DACCLR = 1'b1;     // dac clear




endmodule
